#ifndef __VECTOROPS__
#define __VECTOROPS__

#include "refloat.h"
#include "cxfloat.h"
#include "Pincushion.h"
#include <vector>


class VectorOps
{
  public:
    VectorOps(std::vector<SeamStress::Seamstress*>* ss);
    ~VectorOps();
    
    void copyVector(const refloat_vec* input, refloat_vec* output, unsigned long int offset=0, unsigned long int offset2=0);
    void reverseCopy(const refloat_vec* input, refloat_vec* output);
    void negateVector(refloat_vec* input, refloat_vec* output);
    void reciprocateVector(refloat_vec* input, refloat_vec* output);
    void addVector(const refloat_vec* input, refloat_vec* output);
    void subVector(const refloat_vec* input, refloat_vec* output);
    void divVector(refloat_vec* input, refloat_vec* output);
    void scaleVector(refloat_vec* input, refloat& scale);
    void dotProduct(const refloat_vec* input1, const refloat_vec* input2, refloat& value);
    void setVector(refloat_vec* input, const refloat& val);
    void elementWiseMultiply(const refloat_vec* input, refloat_vec* output);
    void addMul(const refloat_vec* input1, const refloat_vec* input2, refloat_vec* output, refloat& scale);
    
    void negateVector(cxfloat_vec* input, cxfloat_vec* output);
    void setVector(cxfloat_vec* input, const cxfloat& val);
    void addVector(cxfloat_vec* input, cxfloat_vec* output);
    void subVector(cxfloat_vec* input, cxfloat_vec* output);
    void divVector(cxfloat_vec* input, cxfloat_vec* output);
    void elementWiseMultiply(const cxfloat_vec* input, cxfloat_vec* output);
    void scaleVector(cxfloat_vec* input, cxfloat& scale);
    void copyVector(const cxfloat_vec* input, cxfloat_vec* output, unsigned long int offset=0, unsigned long int offset2=0);
    void reciprocateVector(cxfloat_vec* input, cxfloat_vec* output);
    void reverseCopy(const cxfloat_vec* input, cxfloat_vec* output);
    void conjugateVector( const cxfloat_vec* input, cxfloat_vec* output );
    void realVector( const cxfloat_vec* input, refloat_vec* output );
    void copyVector(const refloat_vec* input, cxfloat_vec* output, unsigned long int offset=0, unsigned long int offset2=0);
    void dotProduct(const cxfloat_vec* input1, const cxfloat_vec* input2, refloat& value);
    
  private:
    SeamStress::Pincushion<VectorOps> pins;
    unsigned long int nthreads;
    const refloat_vec* vecpointer1;
    const refloat_vec* vecpointer4;
    refloat_vec* vecpointer2;
    refloat_vec* vecpointer3;
    const refloat* val1;
    unsigned long int thread_tot;
    unsigned long int thread_var1;
    unsigned long int thread_var2;
    
    const cxfloat_vec* cxvecpointer1;
    const cxfloat_vec* cxvecpointer4;
    cxfloat_vec* cxvecpointer2;
    const cxfloat* cxval1;
    
    void copyVectorThread(void* arg);
    void reverseCopyThread(void* arg);
    void negateVectorThread(void* arg);
    void reciprocateVectorThread(void* arg);
    void addVectorThread(void* arg);
    void subVectorThread(void* arg);
    void elementWiseMultiplyThread(void* arg);
    void divVectorThread(void* arg);
    void scaleVectorThread(void* arg);
    void dotProductThread1(void* arg);
    void dotProductThread2(void* arg);
    void setVectorThread(void* arg);
    void addMulThread(void* arg);
    
    void negateVectorCxThread(void* arg);
    void setVectorCxThread(void* arg);
    void addVectorCxThread(void* arg);
    void subVectorCxThread(void* arg);
    void divVectorCxThread(void* arg);
    void elementWiseMultiplyCxThread(void* arg);
    void scaleVectorCxThread(void* arg);
    void copyVectorCxThread(void* arg);
    void reciprocateVectorCxThread(void* arg);
    void reverseCopyCxThread(void* arg);
    void conjugateVectorCxThread(void* arg);
    void realVectorThread(void* arg);
    void copyVectorReCxThread(void* arg);
    void dotProductCxThread1(void* arg);
};



#endif
